#include "EDBaseAfx.h"
#include "Bundle.h"

///BundleData -------------------------------------------------------------
BundleData::BundleData() :m_DataType(BUNDATA_NULL)
{
	ZeroMemory(&m_Value, sizeof(m_Value));
}

BundleData::BundleData(const BundleData &src) :m_DataType(BUNDATA_NULL)
{
	ZeroMemory(&m_Value, sizeof(m_Value));
	this->operator = (src);
}

BundleData& BundleData::operator=(const BundleData& src)
{
	if (BUNDATA_NULL == m_DataType || m_DataType == src.m_DataType) 
	{
		m_DataType = src.m_DataType;
		switch (m_DataType)
		{
		case BUNDATA_STRINGA:
			{	
				setStringA(src.m_Value.u_stringA);
			}
			break;

		case BUNDATA_STRINGW:
			{
				setStringW(src.m_Value.u_stringW);
			}
			break;
	
		case BUNDATA_IUNKNOWN:
			{
				setIUnknown(src.m_Value.u_iunknown);
			}
			break;
		case BUNDATA_INT:
		case BUNDATA_DOUBLE:
		default:
			{
				memcpy(&m_Value, &src.m_Value, sizeof(m_Value));
			}
			break;
		}
	}
	return *this;
}

BundleData::~BundleData()
{
	if (BUNDATA_STRINGA == m_DataType && m_Value.u_stringA) 
	{
		free((void*)m_Value.u_stringA);
	}
	if (BUNDATA_STRINGW == m_DataType && m_Value.u_stringW) 
	{
		free((void*)m_Value.u_stringW);
	}
	if (BUNDATA_IUNKNOWN == m_DataType && m_Value.u_iunknown) 
	{
		m_Value.u_iunknown->Release();
		m_Value.u_iunknown = NULL;
	}
}

bool BundleData::setInt(int data)
{
	if (BUNDATA_NULL == m_DataType ||BUNDATA_INT == m_DataType)
	{
		m_Value.u_int = data;
		m_DataType	  = BUNDATA_INT;
		return true;
	}
	return false;
}

bool BundleData::setDouble(double data)
{
	if (BUNDATA_NULL == m_DataType ||BUNDATA_DOUBLE == m_DataType) 
	{
		m_Value.u_double = data;
		m_DataType		 = BUNDATA_DOUBLE;
		return true;
	}
	return false;
}

bool BundleData::setStringA(LPCSTR data)
{
	if (BUNDATA_NULL == m_DataType ||BUNDATA_STRINGA == m_DataType) 
	{
		if (IsValidString(data)) 
		{
			if (m_Value.u_stringA) 
			{
				free((void*)m_Value.u_stringA);
				m_Value.u_stringA = NULL;
			}
			m_Value.u_stringA = _strdup(data);
		} 
		else 
		{
			m_Value.u_stringA = NULL;
		}
		m_DataType = BUNDATA_STRINGA;
		return true;
	}
	return false;
}

bool BundleData::setStringW(LPCWSTR data)
{
	if (BUNDATA_NULL == m_DataType || BUNDATA_STRINGW == m_DataType) 
	{
		if (IsValidString(data))
		{
			if (m_Value.u_stringW) 
			{
				free((void*)m_Value.u_stringW);
				m_Value.u_stringW = NULL;
			}
			m_Value.u_stringW = _wcsdup(data);
		}
		else 
		{
			m_Value.u_stringW = NULL;
		}
		m_DataType = BUNDATA_STRINGW;
		return true;
	}
	return false;
}

bool BundleData::setIUnknown(IUnknown* data)
{
	if (BUNDATA_NULL == m_DataType || BUNDATA_IUNKNOWN == m_DataType)
	{
		if (data)
		{
			data->AddRef();
		}
		if (m_Value.u_iunknown)
		{
			m_Value.u_iunknown->Release();
			m_Value.u_iunknown = NULL;
		}
		m_Value.u_iunknown = data;
		m_DataType = BUNDATA_IUNKNOWN;
		return true;
	}
	return false;
}

bool BundleData::setVoidPtr(void* data)
{
	if (BUNDATA_NULL == m_DataType ||BUNDATA_VOID == m_DataType) 
	{
		m_Value.u_extra = data;
		m_DataType		 = BUNDATA_VOID;
		return true;
	}
	return false;
}

int BundleData::getInt()
{
	if (BUNDATA_INT == m_DataType)
	{
		return m_Value.u_int;
	}
	return 0;
}

double BundleData::getDouble()
{
	if (BUNDATA_DOUBLE == m_DataType) 
	{
		return m_Value.u_double;
	}
	return 0;
}

LPCSTR BundleData::getStringA()
{
	if (BUNDATA_STRINGA == m_DataType) 
	{
		return NULL == m_Value.u_stringA?"":m_Value.u_stringA;
	}
	return NULL;
}

LPCWSTR BundleData::getStringW()
{
	if (BUNDATA_STRINGW == m_DataType) 
	{
		return NULL == m_Value.u_stringW?L"":m_Value.u_stringW;
	}
	return NULL;
}

IUnknown* BundleData::getIUnknown()
{
	if (BUNDATA_IUNKNOWN == m_DataType)
	{
		// addRef
		if (m_Value.u_iunknown) m_Value.u_iunknown->AddRef();
		return m_Value.u_iunknown;
	}
	return NULL;
}

void* BundleData::getVoidPtr()
{
	if (BUNDATA_VOID == m_DataType) 
	{
		return m_Value.u_extra;
	}
	return NULL;
}

///BundleImpl ------------------------------------------------------------------------
#define _GP_BNUDLE_DEF_KEY_DEF			 "BD!DEF"
void BundleImpl::clear()
{
	t_mapKeyValue clearMapBundle;
	clearMapBundle.swap(m_MapKeyValue);
}

int BundleImpl::size()
{
	return (int)m_MapKeyValue.size();
}

bool BundleImpl::remove(LPCSTR key)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		m_MapKeyValue.erase(iter);
		return true;
	}
	return false;
}

bool BundleImpl::hasKey(LPCSTR key)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		return true;
	}
	return false;
}

bool BundleImpl::putInt(LPCSTR key, int data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setInt(data);
	} 
	else
	{
		BundleData anyValue;
		bSuccess = anyValue.setInt(data);
		m_MapKeyValue[key] = anyValue;
	}
	return bSuccess;
}

bool BundleImpl::putDouble(LPCSTR key, double data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setDouble(data);
	}
	else 
	{
		BundleData anyValue;
		bSuccess = anyValue.setDouble(data);
		m_MapKeyValue[key] = anyValue;
	}
	return bSuccess;
}

bool BundleImpl::putString(LPCSTR key, LPCSTR data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setStringA(data);
	} 
	else
	{
		t_mapKeyValue::_Pairib pair = m_MapKeyValue.insert(t_mapKeyValue::value_type(key, BundleData()));
		if (pair.second)
		{
			BundleData& anyValue = pair.first->second;
			bSuccess = anyValue.setStringA(data);
		}
	}
	return bSuccess;
}

bool BundleImpl::putStringW(LPCSTR key, LPCWSTR data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setStringW(data);
	} 
	else 
	{
		t_mapKeyValue::_Pairib pair = m_MapKeyValue.insert(t_mapKeyValue::value_type(key, BundleData()));
		if (pair.second) 
		{
			BundleData& anyValue = pair.first->second;
			bSuccess = anyValue.setStringW(data);
		}
	}
	return bSuccess;
}

bool BundleImpl::putIUnknownPtr(LPCSTR key, IUnknown* data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setIUnknown(data);
	} 
	else 
	{
		BundleData anyValue;
		bSuccess = anyValue.setIUnknown(data);
		m_MapKeyValue[key] = anyValue;
	}
	return bSuccess;
}

bool BundleImpl::putVoidPtr(LPCSTR key, void* data)
{
	bool bSuccess = false;
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		bSuccess = anyValue.setVoidPtr(data);
	}
	else 
	{
		BundleData anyValue;
		bSuccess = anyValue.setVoidPtr(data);
		m_MapKeyValue[key] = anyValue;
	}
	return bSuccess;
}

int BundleImpl::getInt(LPCSTR key, int defData/* = 0*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;

	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		return anyValue.getInt();
	}
	return defData;
}

double BundleImpl::getDouble(LPCSTR key, double defData/* = 0*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		return anyValue.getDouble();
	}
	return defData;
}

LPCSTR BundleImpl::getString(LPCSTR key, LPCSTR defData/* = NULL*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter) 
	{
		BundleData& anyValue = iter->second;
		return anyValue.getStringA();
	}
	return defData;
}

LPCWSTR BundleImpl::getStringW(LPCSTR key, LPCWSTR defData/* = NULL*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;

	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		return anyValue.getStringW();
	}
	return defData;
}

IUnknown* BundleImpl::getIUnknownPtr(LPCSTR key, IUnknown* defData/* = NULL*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		return anyValue.getIUnknown();
	}
	return defData;
}

void* BundleImpl::getVoidPtr(LPCSTR key, void* defData /*= NULL*/)
{
	if (!IsValidString(key)) key = _GP_BNUDLE_DEF_KEY_DEF;
	t_mapKeyValue::iterator iter = m_MapKeyValue.find(key);
	if (m_MapKeyValue.end() != iter)
	{
		BundleData& anyValue = iter->second;
		return anyValue.getVoidPtr();
	}
	return defData;
}

///Bundle ---------------------------------------------------------------------------
Bundle::Bundle()
{
	m_pBundleImpl.Attach(new BundleImpl);
}

Bundle::Bundle(const Bundle& src)
{
	m_pBundleImpl.reset(src.m_pBundleImpl);
}

Bundle& Bundle::operator=(const Bundle& src)
{
	m_pBundleImpl.reset(src.m_pBundleImpl);
	return *this;
}

Bundle::~Bundle()
{
	m_pBundleImpl.Release();
}

Bundle Bundle::clone()
{
	Bundle cloneBundle;
	if (cloneBundle.m_pBundleImpl) 
	{
		cloneBundle.m_pBundleImpl->operator =(*m_pBundleImpl);
	}
	return cloneBundle;
}

void Bundle::clear()
{
	m_pBundleImpl->clear();
}

int Bundle::size() const
{
	return m_pBundleImpl->size();
}

bool Bundle::remove(LPCSTR key)
{
	return m_pBundleImpl->remove(key);
}

bool Bundle::hasKey(LPCSTR key) const
{
	return m_pBundleImpl->hasKey(key);
}

bool Bundle::putInt(LPCSTR key, int data)
{
	return m_pBundleImpl->putInt(key, data);
}

bool Bundle::putDouble(LPCSTR key, double data)
{
	return m_pBundleImpl->putDouble(key, data);
}

bool Bundle::putString(LPCSTR key, LPCSTR data)
{
	return m_pBundleImpl->putString(key, data);
}

bool Bundle::putStringW(LPCSTR key, LPCWSTR data)
{
	return m_pBundleImpl->putStringW(key, data);
}

bool Bundle::putUTF8String(LPCSTR key, LPCSTR data)
{
	return m_pBundleImpl->putString(key, data);
}

bool Bundle::putIUnknownPtr(LPCSTR key, IUnknown* data)
{
	return m_pBundleImpl->putIUnknownPtr(key, data);
}

bool Bundle::putVoidPtr(LPCSTR key, void* data)
{
	return m_pBundleImpl->putVoidPtr(key,data);
}

int Bundle::getInt(LPCSTR key, int defData /*= 0*/) const
{
	return m_pBundleImpl->getInt(key, defData);
}

double Bundle::getDouble(LPCSTR key, double defData /*= 0*/) const
{
	return m_pBundleImpl->getDouble(key, defData);
}

LPCSTR Bundle::getString(LPCSTR key, LPCSTR defData /*= ""*/) const
{
	return m_pBundleImpl->getString(key, defData);
}

LPCWSTR Bundle::getStringW(LPCSTR key, LPCWSTR defData /*= L""*/) const
{
	return m_pBundleImpl->getStringW(key, defData);
}

LPCSTR Bundle::getUTF8String(LPCSTR key, LPCSTR defData /*= ""*/) const
{
	return m_pBundleImpl->getString(key, defData);
}

IUnknown* Bundle::getIUnknownPtr(LPCSTR key, IUnknown* defData /*= NULL*/) const
{
	return m_pBundleImpl->getIUnknownPtr(key, defData);
}

void* Bundle::getVoidPtr(LPCSTR key, void* defData /*= NULL*/) const
{
	return m_pBundleImpl->getVoidPtr(key, defData);
}
